package com.hk;

import cn.dev33.satoken.fun.SaFunction;
import com.baomidou.mybatisplus.extension.api.R;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import org.junit.Test;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 对象或者方法引用demo
 */
@SpringBootTest
public class ObjectAndMethodQuoteDemo {

    @Test
    public void test01() {

        Student student = new Student();
        student.setName("zs");
        student.setAge(null);
        Student student2 = new Student();
        student2.setName("ls");
        student2.setAge("999");
        List<Student> students = Arrays.asList(student, student2);
        //value会发生空指针
//        Map<String, String> collect = students.stream()
//                .collect(Collectors.toMap(Student::getName, Student::getAge));
        //这样就不会空指针了
        Map<String, String> collect = students.stream()
                .filter(o -> StringUtils.isNotBlank(o.getAge()))
                .collect(Collectors.toMap(Student::getName, Student::getAge));

        Map<Object, Object> map2 = students.stream().collect(HashMap::new, (m, v) -> m.put(v.getName(), v.getAge()), HashMap::putAll);

        System.out.println(collect);
        System.out.println(map2);

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~");

        // Consumer是一个函数式接口，主要用于lambda表达式
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("con1");
        //>对象::实例方法名
        // Consumer 中的 void accept(T t)
        // void accept(T t) 与 打印流中的void println(T t) 参数类型和返回值一致，因此可以用方法引用
        Consumer<String> con2 = System.out::println;
        con2.accept("con2");

        //＞类::静态方法名
        // 情况二：类::静态方法
        // Comparator 中的 int compare(T t1,T t2)
        // int compare(T t1,T t2) 与 Integer中的int compare(T t1,T t2) 参数类型和返回值一致，因此可以用方法引用
        Comparator<Integer> com3 = (t1, t2) -> Integer.compare(t1, t2);
        System.out.println(com3.compare(12, 13));

        Comparator<Integer> com4 = Integer::compare;
        System.out.println(com4.compare(12, 13));
        //＞类::实例方法名
        // 情况三：类::实例方法名 (有难度）---前面方法引用的要求针对的是情况一和情况二，对情况三不适用
        // Comparator 中的 int compare(T t1,T t2)
        // String 中的 int t1.compareTo(t2) // T t1 作为compareTo的调用者，T的类型作为 类::实例方法名 中的类
        Comparator<String> com5 = (s1, s2) -> s1.compareTo(s2);
        System.out.println(com5.compare("D", "B"));

        Comparator<String> com6 = String::compareTo;
        System.out.println(com6.compare("D", "B"));

    }

    @Test
    public void test02() {
        Employee2 employee2 = new Employee2("zs", 18, 1223);
        Supplier<String> sup = () -> employee2.getName();
        System.out.println(sup.get());


        Supplier<String> sup2 = employee2::getName;
        System.out.println(sup2.get());

        //构造器引用，调用无参构造
        Supplier<Employee2> employee2Supplier = Employee2::new;
        System.out.println(employee2Supplier.get());
        //构造器引用，有参构造，前提是一定要有构造方法要不会报错~~~
        Function<Integer, Employee2> fun2 = Employee2::new;
        System.out.println(fun2.apply(6));

        System.out.println("---------------------------");
        Supplier<String> staticMethod = Employee2::print;
        System.out.println(staticMethod);

        Map<Object, Object> map = employee2.createObject(HashMap::new);
        Supplier<Map> map2 = HashMap::new;

        map.put("name", "zs");
        System.out.println(map);
    }

    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    class Student {
        private String name;
        private String age;
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Employee2 {

    private String name;
    private Integer age;
    private double salary;

    public Employee2(Integer age) {
        this.age = age;
    }

    public static String print() {
        System.out.println("我执行了~~");
        return "我执行了~~";
    }

    public static <T> T createObject(Supplier<T> supplier) {
        return supplier.get();
    }

    @Override
    public String toString() {
        return "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary;
    }
}